package br.com.sgc.session;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import br.com.sgc.dao.ContasReceberDao;
import br.com.sgc.entities.financeiro.ContasReceber;
import br.com.sgc.entities.financeiro.PedidoVenda;
import br.com.sgc.entities.geral.Clinica;
import br.com.sgc.enuns.TipoDesconto;
import br.com.sgc.enuns.TipoOrdenacao;
import br.com.sgc.exception.ValidacaoException;

@Stateless
public class ContasReceberSession extends GenericSession<ContasReceber> {

	private static final long serialVersionUID = 3438189385945163452L;
	
	@EJB private PedidoVendaSession pedidoVendaSession;
	
	@EJB private ContasReceberDao dao;
	
	public void save(List<ContasReceber> list, PedidoVenda pedidoVenda) throws ValidacaoException {
		pedidoVenda.setFinalizado(true);
		pedidoVenda.setGuardado(false);
		pedidoVenda.setCancelado(false);
		
		
		if(pedidoVenda.getId() != null){
			pedidoVenda = pedidoVendaSession.update(pedidoVenda);
		} else {
			pedidoVenda = pedidoVendaSession.save(pedidoVenda);
		}
		
		pedidoVendaSession.atualizarEstoque(pedidoVenda);
		
		pedidoVenda.setValorTotalVenda(new BigDecimal(0.0));
		BigDecimal total = new BigDecimal(0.0);
		
		for(ContasReceber conta: list){
			conta.setPedidoVenda(pedidoVenda);
			total = total.add(conta.getValorTotal());
			dao.insert(conta);
		}
		pedidoVenda.setValorTotalVenda(total);
		pedidoVendaSession.update(pedidoVenda);
		
		
		
	}

	public List<ContasReceber> parcelarConta(ContasReceber contasReceber,
			List<ContasReceber> listParcelas, Integer quantidadeParcelas,
			Boolean quitarPrimeiroPagamento, Clinica clinica, PedidoVenda pedidoVenda, Integer intervalo) {
		
		listParcelas = new ArrayList<ContasReceber>();
		BigDecimal valorTotal = contasReceber.getValorPrincipal();
		BigDecimal juros = new BigDecimal(0.0);
		BigDecimal multa = new BigDecimal(0.0);
		BigDecimal desconto = new BigDecimal(0.0);
		
		if(contasReceber.getJuros() != null)
			juros = contasReceber.getJuros();
		
		if(contasReceber.getMulta() != null)
			multa = contasReceber.getMulta();
		
		if(contasReceber.getTipoDesconto() != null && contasReceber.getDesconto() != null){
			if(contasReceber.getTipoDesconto().equals(TipoDesconto.MONETARIO)){
				desconto = contasReceber.getDesconto();
			} else if (contasReceber.getTipoDesconto().equals(TipoDesconto.PERCENTUAL)){
				desconto = valorTotal.multiply(contasReceber.getDesconto()).divide(new BigDecimal(100), RoundingMode.HALF_UP);
			}
		}
		
		BigDecimal totalParcelas = new BigDecimal(0.0);
		BigDecimal jurosParcela = new BigDecimal(0.0);
		BigDecimal multaParcela = new BigDecimal(0.0);
		BigDecimal descontoParcela = new BigDecimal(0.0);
		BigDecimal parcelas = new BigDecimal(quantidadeParcelas);
		Boolean quitarPrimeira = quitarPrimeiroPagamento;
		
		
		Calendar calendar = Calendar.getInstance();
		
		for(int i= 1; i <= quantidadeParcelas; i++){
			ContasReceber parcela = new ContasReceber();
			parcela.setNumeroParcela(String.valueOf(i));
			
			
			parcela.setJuros(juros.divide(parcelas, RoundingMode.HALF_UP));
			jurosParcela = jurosParcela.add(parcela.getJuros());
			
			parcela.setMulta(multa.divide(parcelas, RoundingMode.HALF_UP));
			multaParcela = multaParcela.add(parcela.getMulta());
			
			parcela.setValorPrincipal(valorTotal.divide(parcelas, RoundingMode.HALF_UP));
			totalParcelas = totalParcelas.add(parcela.getValorPrincipal());
			
			parcela.setDesconto(desconto.divide(parcelas, RoundingMode.HALF_UP));
			descontoParcela = descontoParcela.add(parcela.getDesconto());
			
			parcela.setValorTotal(parcela.getValorPrincipal().add(parcela.getMulta()).add(parcela.getJuros()).subtract(parcela.getDesconto()));
			parcela.setFormaPagamento(contasReceber.getFormaPagamento());

			if(!quitarPrimeira){
				parcela.setQuitado(false);
				calendar.add(Calendar.DATE, intervalo);
				parcela.setValorPagamento(new BigDecimal(0.0));
			} else {
				parcela.setQuitado(true);
				parcela.setDataRealPagamento(calendar.getTime());
				parcela.setValorPagamento(parcela.getValorTotal());
				quitarPrimeira = false;
			}
			
			parcela.setDataPrevisaoPagamento(calendar.getTime());
			parcela.setTipoDesconto(contasReceber.getTipoDesconto());
			
			
			parcela.setClinica(clinica);
			parcela.setPedidoVenda(pedidoVenda);
			listParcelas.add(parcela);
			
		}
		
		return listParcelas;
	}

	public List<ContasReceber> findAllByPedidoVenda(PedidoVenda pedidoVenda) {
		return dao.findAllByPedidoVenda(pedidoVenda);
	}
	
	public List<ContasReceber> findAll(ContasReceber modelClass, Long clinicaId,
			Integer startPage, Integer maxPage, String orderField,
			Boolean initializeDependecies, TipoOrdenacao ordenacao) {
		return dao.findAll(modelClass, clinicaId, startPage, maxPage, orderField,
				initializeDependecies, ordenacao);
		
	}
	
	@Override
	public Long count(ContasReceber modelClass, Long clinicaId) {
		return dao.count(modelClass, clinicaId);
	}

	public ContasReceber showDetalhes(ContasReceber contasReceber) {
		contasReceber = dao.findById(ContasReceber.class, contasReceber.getId(), true);
		if(!contasReceber.getQuitado()){
			contasReceber.setValorPagamento(contasReceber.getValorTotal());
		}
		if(contasReceber.getDataRealPagamento() == null){ 
			contasReceber.setDataRealPagamento(new Date());
		}
		return contasReceber;
	}

	public void baixarPagamento(ContasReceber contasReceber) {
		contasReceber.setQuitado(true);
		dao.update(contasReceber);
	}

	public BigDecimal findTotalContasPorData(Date dataCaixa, Clinica clinica) {
		return dao.findTotalContasPorData(dataCaixa, clinica);
	}

}
